/*
 * gcc.hpp
 *
 *  Created on: 4 May 2013
 *      Author: maneg
 */

#ifndef GCC_HPP_
#define GCC_HPP_
#include "burp.hpp"

namespace burp{

	class gpp : public burp::compiler, public burp::linker{
	public:
		typedef std::vector<std::string> argument_set_t;
		static const std::string debug() {return "-g3";};
		static const std::string warning_level(int level){
			switch(level){
			default:
				return "-Wall";
			case 0:
				return "-w";
			case 4:
				return "-Wextra";
			}
		}

		static const std::string optimization_level(int level){
			switch(level){
			default:
				return "-O2";
			case 0:
				return "-O0";
			case 1:
				return "-O1";
			case 3:
				return "-O3";
			}
		}


		static const std::string include_directory_prefix(){return "-I";}
		static const std::string preprocessor_definition_prefix(){return "-D";}



	public:
		gpp() : burp::compiler("g++","gcc"), burp::linker("g++", "gcc"){}

		virtual bool is_uptodate(const file& src, const file& obj) const{
			file d_file(path(file_change_extention(obj,".d")),false);
			if( !obj.exists() || !d_file.exists()){
				return false;
			}
			time_t sl = src.last_modified();
			time_t ol = obj.last_modified();
			if(sl >= ol) return false;
			return parse_dfile(d_file,ol);
		}

		virtual void translate(argument_set_t& res, const compiler_configuration& arg) const {
			res.push_back("-c");
			if(arg.is_debug()) res.push_back(debug());
#ifndef WIN32
			if(arg.is_shared()) res.push_back("-fPIC");
#endif
			res.push_back(warning_level(arg.warning_level()));
			res.push_back(optimization_level(arg.optimization_level()));

			const std::vector<std::string>& extra = arg.custom_arguments(compiler_name());
			for(std::vector<std::string>::const_iterator it = extra.begin(); it != extra.end();++it){
				res.push_back(*it);
			}

			res.push_back("-MMD");

			for(compiler_configuration::dirvec_t::const_iterator it = arg.include_directories().begin();it!=arg.include_directories().end();++it){
				res.push_back(include_directory_prefix() + it->native_path());
			}

			for(compiler_configuration::ssvec_t::const_iterator it = arg.preprocessor_definitions().begin();it!=arg.preprocessor_definitions().end();++it){
				res.push_back(preprocessor_definition_prefix() + *it);
			}

		}

		virtual void translate(argument_set_t& pre_res, argument_set_t& post_res,const linker_configuration& arg) const {

			pre_res.push_back("-o " + arg.output_file().native_path());

			std::ostringstream ostr;
#ifdef WIN32
			ostr << "-Wl";
			const linker_configuration::ssvec_t& cvec = arg.custom_arguments("gcc");
			for(linker_configuration::ssvec_t::const_iterator it = cvec.begin();it!=cvec.end();++it){
				ostr << "," << *it;
			}
			ostr << ",--out-implib," << arg.output_file().native_path().substr(0,arg.output_file().native_path().find_last_of('.')) << "." <<platform_traits::static_library_file_extention;
			pre_res.push_back(ostr.str());
#endif
			if(arg.is_shared()){
				pre_res.push_back("-shared");
			}



			for(linker_configuration::pathvec_t::const_iterator it = arg.link_libraries().begin();it!=arg.link_libraries().end();++it){
				post_res.push_back("-l"+it->native_path());
			}
		}
	};



}




#endif /* GCC_HPP_ */
